package cn.t.service.user;

import cn.t.core.exception.BizException;
import cn.t.core.mode.YesNoEnum;
import cn.t.core.service.ServiceImpl;
import cn.t.core.enums.base.BaseStatusEnum;
import cn.t.core.enums.base.CommonError;
import cn.t.model.user.ResourceInfoDO;
import cn.t.model.user.RoleResourceDO;
import cn.t.repository.user.ResourceInfoRepository;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.t.constants.Constants.REDIS_KEY__RESOURCE_INFO;


/**
 * 资源权限表领域服务
 *
 * @author l
 */
@Slf4j
@Service
@AllArgsConstructor
public class ResourceInfoService extends ServiceImpl<ResourceInfoDO, ResourceInfoRepository> {

    @Override
    public boolean update(ResourceInfoDO dataDo) {

        if (dataDo.getId().equals(dataDo.getParentId())) {
            String errorMessage = String.format("资源ID与父节点冲突 resourceId=%d parentId=%d", dataDo.getId(), dataDo.getParentId());
            log.error(errorMessage);
            throw new BizException(CommonError.ILLEGAL_PARAMETER, errorMessage);
        }

        return repository.update(dataDo);
    }

    @Override
    public boolean add(ResourceInfoDO dataDo) {
        long resourceId = repository.addAndReturnId(dataDo);
        if (resourceId == dataDo.getParentId()) {
            String errorMessage = String.format("资源ID与父节点冲突 resourceId=%d parentId=%d", resourceId, dataDo.getParentId());
            log.error(errorMessage);
            throw new BizException(CommonError.ILLEGAL_PARAMETER, errorMessage);
        }
        return true;
    }


    @Override
    public ResourceInfoDO findById(Long resourceId) {
        String redisKey = String.format(REDIS_KEY__RESOURCE_INFO, resourceId);
        ResourceInfoDO ret = (ResourceInfoDO) redissonClient.getBucket(redisKey).get();
        if (ret != null && ret.getId() != null & ret.getId().equals(resourceId)) {
            return ret;
        }
        ret = repository.findById(resourceId);
        redissonClient.getBucket(redisKey).set(ret, 1, TimeUnit.HOURS);
        return ret;
    }


    public List<ResourceInfoDO> findByRoleId(Long roleId) {
        List<RoleResourceDO> tmp = roleResourceService.findByRoleId(roleId);
        if (tmp == null) {
            return null;
        }
        return tmp.stream().map(t -> findById(t.getResourceId())).collect(Collectors.toList());

    }

    public Map<Long, ResourceInfoDO> getResourceMap() {

        ResourceInfoDO template = new ResourceInfoDO();
        template.setStatus(String.valueOf(BaseStatusEnum.AVAILABLE.getCode()));
        List<ResourceInfoDO> list = repository.findByModel(template, 0, 10000, "id asc,sort asc", "");
        if (list == null || list.isEmpty()) {
            return null;
        }
        return list.stream().collect(Collectors.toMap(ResourceInfoDO::getId, t -> t));

    }

    public List<ResourceInfoDO> findByParentId(Long id) {

        ResourceInfoDO template = new ResourceInfoDO();
        template.setParentId(id);
        template.setStatus(String.valueOf(BaseStatusEnum.AVAILABLE.getCode()));
        template.setIsDeleted(YesNoEnum.FALSE);

        return repository.findByModel(template, 0, 100, null, null);
    }

    public List<ResourceInfoDO> findByCode(String resourceCode) {
        ResourceInfoDO template = new ResourceInfoDO();
        template.setResourceCode(resourceCode);
        template.setStatus(String.valueOf(BaseStatusEnum.AVAILABLE.getCode()));
        template.setIsDeleted(YesNoEnum.FALSE);

        return repository.findByModel(template, 0, 1000, null, null);
    }

    public List<ResourceInfoDO> findByName(String resourceName) {
        ResourceInfoDO template = new ResourceInfoDO();
        template.setResourceName(resourceName);
        template.setStatus(String.valueOf(BaseStatusEnum.AVAILABLE.getCode()));
        template.setIsDeleted(YesNoEnum.FALSE);

        return repository.findByModel(template, 0, 1000, null, null);
    }


    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RoleResourceService roleResourceService;



}
